from qgis.PyQt.QtWidgets import (QDialog, QVBoxLayout, QListWidget, 
                                QPushButton, QLabel, QHBoxLayout, 
                                QComboBox, QAction, QListWidgetItem)
from qgis.PyQt.QtCore import Qt, pyqtSignal
from qgis.PyQt.QtGui import QIcon
from qgis.core import (QgsProject, QgsWkbTypes, QgsGeometry, 
                      QgsPointXY, QgsFeature, QgsMapLayer,
                      QgsRectangle, QgsPoint, QgsFeatureRequest)
from qgis.gui import (QgsVertexMarker, QgsRubberBand, 
                     QgsMapToolAdvancedDigitizing)
from qgis.utils import iface

class AreaMapTool(QgsMapToolAdvancedDigitizing):
    """
    自定义地图工具类，用于在地图上绘制多边形区域，并在绘制完成后发出信号。
    继承自 QgsMapToolAdvancedDigitizing，支持高级数字化功能。
    """
    # 定义一个信号，当区域绘制完成后发出，携带绘制的 QgsGeometry 对象
    selectionFinished = pyqtSignal(QgsGeometry)

    def __init__(self, canvas, cadDockWidget, dialog):
        """
        构造函数，初始化地图工具。

        :param canvas: QGIS 地图画布对象，用于在地图上绘制和交互。
        :param cadDockWidget: CAD 工具栏控件，用于支持高级数字化功能。
        :param dialog: 与该工具关联的对话框对象，用于进一步的交互。
        """
        # 调用父类构造函数，初始化高级数字化功能
        super().__init__(canvas, cadDockWidget)
        self.dialog = dialog  # 保存关联的对话框对象
        # 创建一个橡胶带对象，用于在地图上绘制多边形
        self.rubber_band = QgsRubberBand(canvas, QgsWkbTypes.PolygonGeometry)
        self.rubber_band.setColor(Qt.blue)  # 设置橡胶带颜色为蓝色
        self.rubber_band.setWidth(1)  # 设置橡胶带宽度为 1

    def canvasPressEvent(self, event):
        """
        地图画布鼠标按下事件处理函数。

        :param event: 鼠标事件对象，包含鼠标按下时的位置等信息。
        """
        # 检查是否为鼠标左键按下
        if event.button() == Qt.LeftButton:
            # 将屏幕坐标转换为地图坐标
            point = self.toMapCoordinates(event.pos())
            # 如果橡胶带中没有顶点（即尚未开始绘制），添加第一个顶点
            if self.rubber_band.numberOfVertices() == 0:
                self.rubber_band.addPoint(point, True)
            # 添加新的顶点到橡胶带中
            self.rubber_band.addPoint(point)

    def canvasMoveEvent(self, event):
        """
        地图画布鼠标移动事件处理函数。

        :param event: 鼠标事件对象，包含鼠标移动时的位置等信息。
        """
        # 如果橡胶带中已经有顶点（即已经开始绘制），则更新最后一个顶点的位置
        if self.rubber_band.numberOfVertices() > 0:
            point = self.toMapCoordinates(event.pos())
            self.rubber_band.movePoint(point)

    def canvasReleaseEvent(self, event):
        """
        地图画布鼠标释放事件处理函数。

        :param event: 鼠标事件对象，包含鼠标释放时的位置等信息。
        """
        # 检查是否为鼠标右键释放
        if event.button() == Qt.RightButton and self.rubber_band.numberOfVertices() > 2:
            # 将橡胶带中的点转换为 QgsGeometry 对象
            geom = self.rubber_band.asGeometry()
            # 发出信号，携带绘制的几何对象
            self.selectionFinished.emit(geom)
            # 重置橡胶带，准备下一次绘制
            self.rubber_band.reset(QgsWkbTypes.PolygonGeometry)
            # 停用当前地图工具
            self.canvas().unsetMapTool(self)

    def deactivate(self):
        """
        地图工具停用时的处理函数。
        """
        # 重置橡胶带，清除绘制的多边形
        self.rubber_band.reset(QgsWkbTypes.PolygonGeometry)
        # 调用父类的停用函数，执行其他必要的清理操作
        super().deactivate()